package com.zbkj.crmeb.chant.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.common.CommonPage;
import com.common.PageParamRequest;
import com.constants.Constants;
import com.crmeb.core.exception.CrmebException;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.utils.DateUtil;
import com.utils.vo.dateLimitUtilVo;
import com.zbkj.crmeb.chant.dao.ChannelDiscountPackageDao;
import com.zbkj.crmeb.chant.model.ChannelDiscountPackage;
import com.zbkj.crmeb.chant.model.ChannelDiscountPackageGoods;
import com.zbkj.crmeb.chant.request.ChannelDiscountPackageRequest;
import com.zbkj.crmeb.chant.response.ChannelDiscountPackageResponse;
import com.zbkj.crmeb.chant.service.ChannelDiscountPackageGoodsService;
import com.zbkj.crmeb.chant.service.ChannelDiscountPackageService;
import com.zbkj.crmeb.store.model.StoreProduct;
import com.zbkj.crmeb.store.model.StoreProductAttrValue;
import com.zbkj.crmeb.store.response.StoreCartResponse;
import com.zbkj.crmeb.store.service.StoreProductAttrValueService;
import com.zbkj.crmeb.store.service.StoreProductService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class ChannelDiscountPackageServiceImpl extends ServiceImpl<ChannelDiscountPackageDao, ChannelDiscountPackage> implements ChannelDiscountPackageService {
    @Autowired
    private ChannelDiscountPackageGoodsService channelDiscountPackageGoodsService;
    @Autowired
    private StoreProductService storeProductService;
    @Autowired
    private StoreProductAttrValueService storeProductAttrValueService;

    /**
     * 功能描述: 保存优惠套餐
     * @Param: [request, merId]
     * @Return: java.lang.Boolean
     * @Author: wangzh
     * @Date: 2023/6/2 14:40
     */
    @Override
    public Boolean saveOrUpdateInfo(ChannelDiscountPackageRequest request, Integer merId) {
        ChannelDiscountPackage channelDiscountPackage = new ChannelDiscountPackage();
        BeanUtils.copyProperties(request, channelDiscountPackage);
        dateLimitUtilVo dateLimit = DateUtil.getDateLimit(request.getActivityTime());
        channelDiscountPackage.setActivityStartTime(DateUtil.strToDate(dateLimit.getStartTime(), Constants.DATE_FORMAT));
        channelDiscountPackage.setActivityEndTime(DateUtil.strToDate(dateLimit.getEndTime(), Constants.DATE_FORMAT));
        channelDiscountPackage.setMerId(merId);
        Map<Integer, BigDecimal> mainProductInfo = request.getMainProductInfo();
        Map<Integer, BigDecimal> collocationProductInfo = Optional.ofNullable(request.getCollocationProductInfo()).orElse(new HashMap<>());
        channelDiscountPackage.setProductCount(mainProductInfo.keySet().size() + collocationProductInfo.keySet().size());
        if (request.getActivityType() == 2) {
            channelDiscountPackage.setActivityTotalPrice(null);
        }
        // 保存获取主键
        boolean save = this.saveOrUpdate(channelDiscountPackage);
        if (!save) {
            return false;
        }
        // 删除商品，再添加
        channelDiscountPackageGoodsService.remove(Wrappers.<ChannelDiscountPackageGoods>lambdaQuery().eq(ChannelDiscountPackageGoods::getActivityId, channelDiscountPackage.getId()));
        List<ChannelDiscountPackageGoods> channelDiscountPackageGoodsList = new ArrayList<>();
        // 主商品
        for (Map.Entry<Integer, BigDecimal> entry : mainProductInfo.entrySet()) {
            ChannelDiscountPackageGoods channelDiscountPackageGoods = new ChannelDiscountPackageGoods();
            channelDiscountPackageGoods.setGoodsType(1);
            channelDiscountPackageGoods.setActivityId(channelDiscountPackage.getId());
            channelDiscountPackageGoods.setProductId(entry.getKey());
            channelDiscountPackageGoods.setCollocationCondition(entry.getValue());
            channelDiscountPackageGoodsList.add(channelDiscountPackageGoods);
        }
        if (request.getActivityType() == 2) {
            // 搭配商品
            for (Map.Entry<Integer, BigDecimal> entry : collocationProductInfo.entrySet()) {
                ChannelDiscountPackageGoods channelDiscountPackageGoods = new ChannelDiscountPackageGoods();
                channelDiscountPackageGoods.setGoodsType(2);
                channelDiscountPackageGoods.setActivityId(channelDiscountPackage.getId());
                channelDiscountPackageGoods.setProductId(entry.getKey());
                channelDiscountPackageGoods.setCollocationCondition(entry.getValue());
                channelDiscountPackageGoodsList.add(channelDiscountPackageGoods);
            }
        }
        return channelDiscountPackageGoodsService.saveBatch(channelDiscountPackageGoodsList);
    }

    @Override
    public Boolean earlyTerminationActivity(Integer id) {
        return this.update(Wrappers.<ChannelDiscountPackage>lambdaUpdate().eq(ChannelDiscountPackage::getId, id)
                .set(ChannelDiscountPackage::getActivityEndTime, new Date()));
    }

    @Override
    public Boolean delDiscountPackage(Integer id) {
        boolean remove = this.removeById(id);
        boolean removeGoods = channelDiscountPackageGoodsService.remove(Wrappers.<ChannelDiscountPackageGoods>lambdaQuery().eq(ChannelDiscountPackageGoods::getActivityId, id));
        return remove && removeGoods;
    }

    @Override
    public CommonPage<ChannelDiscountPackageResponse> getList(String activityName, Integer activityType, Integer status, Integer merId, PageParamRequest request) {
        LambdaQueryWrapper<ChannelDiscountPackage> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ChannelDiscountPackage::getMerId, merId);
        if (StringUtils.isNotBlank(activityName)) {
            queryWrapper.like(ChannelDiscountPackage::getActivityName, activityName);
        }
        if (Objects.nonNull(activityType)) {
            queryWrapper.eq(ChannelDiscountPackage::getActivityType, activityType);
        }
        if (Objects.nonNull(status)) {
            switch (status) {
                case 1:
                    queryWrapper.gt(ChannelDiscountPackage::getActivityStartTime, new Date());
                    break;
                case 2:
                    queryWrapper.gt(ChannelDiscountPackage::getActivityEndTime, new Date())
                            .lt(ChannelDiscountPackage::getActivityStartTime, new Date());
                    break;
                case 3:
                    queryWrapper.lt(ChannelDiscountPackage::getActivityEndTime, new Date());
                    break;
                default:
                    break;
            }
        }
        Page<Object> page = PageHelper.startPage(request.getPage(), request.getLimit());
        List<ChannelDiscountPackage> channelDiscountPackages = this.list(queryWrapper);
        List<ChannelDiscountPackageResponse> channelDiscountPackageResponses = new ArrayList<>();
        if (CollectionUtils.isEmpty(channelDiscountPackages)) {
            return CommonPage.restPage(CommonPage.copyPageInfo(page, channelDiscountPackageResponses));
        }
        for (ChannelDiscountPackage channelDiscountPackage : channelDiscountPackages) {
            ChannelDiscountPackageResponse response = new ChannelDiscountPackageResponse();
            BeanUtils.copyProperties(channelDiscountPackage, response);
            // 未开始
            if (channelDiscountPackage.getActivityStartTime().after(new Date())) {
                response.setStatus(1);
            // 已结束
            } else if (channelDiscountPackage.getActivityEndTime().before(new Date())) {
                response.setStatus(3);
            } else {
                response.setStatus(2);
            }
            channelDiscountPackageResponses.add(response);
        }

        return CommonPage.restPage(CommonPage.copyPageInfo(page, channelDiscountPackageResponses));
    }

    @Override
    public ChannelDiscountPackageResponse getInfo(Integer id) {
        ChannelDiscountPackageResponse response = new ChannelDiscountPackageResponse();
        ChannelDiscountPackage channelDiscountPackage = this.getById(id);
        if (Objects.isNull(channelDiscountPackage)) {
            return response;
        }
        BeanUtils.copyProperties(channelDiscountPackage, response);
        response.setActivityStartTime(DateUtil.dateToStr(channelDiscountPackage.getActivityStartTime(), Constants.DATE_FORMAT));
        response.setActivityEndTime(DateUtil.dateToStr(channelDiscountPackage.getActivityEndTime(), Constants.DATE_FORMAT));
        List<ChannelDiscountPackageGoods> channelDiscountPackageGoodsList = channelDiscountPackageGoodsService.getList(id);
        // 商品信息为空，直接返回
        if (CollectionUtils.isEmpty(channelDiscountPackageGoodsList)) {
            return response;
        }
        // 按商品类型分类
        Map<Integer, List<ChannelDiscountPackageGoods>> map = channelDiscountPackageGoodsList.stream().collect(Collectors.groupingBy(ChannelDiscountPackageGoods::getGoodsType));
        Map<Integer, ChannelDiscountPackageGoods> goodsMap = channelDiscountPackageGoodsList.stream().collect(Collectors.toMap(ChannelDiscountPackageGoods::getProductId, e -> e, (v1, v2) -> v1));
        List<Integer> productIds = channelDiscountPackageGoodsList.stream().map(ChannelDiscountPackageGoods::getProductId).collect(Collectors.toList());
        List<StoreProduct> products = storeProductService.getListInIds(productIds);
        // 商品所属规格
        List<StoreProductAttrValue> storeProductAttrValues = storeProductAttrValueService.list(Wrappers.<StoreProductAttrValue>lambdaQuery().in(StoreProductAttrValue::getProductId, productIds));
        // 各商品规格
        Map<Integer, List<StoreProductAttrValue>> valuesMap = storeProductAttrValues.stream().collect(Collectors.groupingBy(StoreProductAttrValue::getProductId));
        Map<String, List<StoreProduct>> productInfo = new HashMap<>();
        List<StoreProduct> mainProductInfo = new ArrayList<>();
        List<StoreProduct> collocationProductInfo = new ArrayList<>();
        for (StoreProduct storeProduct : products) {
            storeProduct.setStoreProductAttrValues(valuesMap.get(storeProduct.getId()));
            // 主商品id列表
            List<Integer> mainList = Optional.ofNullable(map.get(1)).orElse(new ArrayList<>()).stream().map(ChannelDiscountPackageGoods::getProductId).collect(Collectors.toList());
            // 搭配商品id列表
            List<Integer> collocationList = Optional.ofNullable(map.get(2)).orElse(new ArrayList<>()).stream().map(ChannelDiscountPackageGoods::getProductId).collect(Collectors.toList());
            if (mainList.contains(storeProduct.getId())) {
                BigDecimal collocationCondition = goodsMap.get(storeProduct.getId()).getCollocationCondition();
                if (channelDiscountPackage.getActivityType() == 1) {
                    storeProduct.setPackageDiscountInfo(collocationCondition.intValue());
                } else {
                    storeProduct.setPackageDiscountInfo(collocationCondition);
                }
                mainProductInfo.add(storeProduct);
            } else if (collocationList.contains(storeProduct.getId())) {
                storeProduct.setPackageDiscountInfo(goodsMap.get(storeProduct.getId()).getCollocationCondition());
                collocationProductInfo.add(storeProduct);
            }
        }
        productInfo.put("mainProductInfo", mainProductInfo);
        productInfo.put("collocationProductInfo", collocationProductInfo);
        response.setProductInfo(productInfo);
        return response;
    }

    @Override
    public List<ChannelDiscountPackage> getListInIds(List<Integer> activityIds, Integer merId) {
        return this.list(Wrappers.<ChannelDiscountPackage>lambdaQuery()
                .in(ChannelDiscountPackage::getId, activityIds)
                .eq(ChannelDiscountPackage::getMerId, merId));
    }

    @Override
    public BigDecimal getPayPrice(Integer activityId, List<StoreCartResponse> storeCartResponses) {
        ChannelDiscountPackage channelDiscountPackage = this.getById(activityId);
        List<Integer> productIds = storeCartResponses.stream().map(StoreCartResponse::getProductId).collect(Collectors.toList());
        // 固定套餐，直接返回价格
        if (channelDiscountPackage.getActivityType() == 1) {
            List<ChannelDiscountPackageGoods> channelDiscountPackageGoodsList = channelDiscountPackageGoodsService.getList(activityId);
            List<Integer> shouldProductIds = channelDiscountPackageGoodsList.stream().map(ChannelDiscountPackageGoods::getProductId).collect(Collectors.toList());
            // 对提交的订单商品进行检查，是否满足套餐必须购买商品
            if (productIds.size() != shouldProductIds.size() || !productIds.containsAll(shouldProductIds)) {
                throw new CrmebException("订单商品未包含所有必须购买商品！");
            }
            return channelDiscountPackage.getActivityTotalPrice();
        }
        List<ChannelDiscountPackageGoods> channelDiscountPackageGoodsList = channelDiscountPackageGoodsService.getList(activityId);
        Map<Integer, List<ChannelDiscountPackageGoods>> map = channelDiscountPackageGoodsList.stream().collect(Collectors.groupingBy(ChannelDiscountPackageGoods::getGoodsType));
        // 搭配套餐中的主商品
        List<Integer> mustProductIds = map.get(1).stream().map(ChannelDiscountPackageGoods::getProductId).collect(Collectors.toList());
        if (!productIds.containsAll(mustProductIds)) {
            throw new CrmebException("订单商品未包含所有必须购买商品！");
        }
        // 过滤搭配商品，计算订单价格
        channelDiscountPackageGoodsList = channelDiscountPackageGoodsList.stream().filter(e -> productIds.contains(e.getProductId())).collect(Collectors.toList());
        BigDecimal payPrice = BigDecimal.ZERO;
        for (ChannelDiscountPackageGoods channelDiscountPackageGoods : channelDiscountPackageGoodsList) {
            payPrice = payPrice.add(channelDiscountPackageGoods.getCollocationCondition());
        }
        return payPrice;
    }
}
